package huu.eventLoop;

import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author huu
 * @create 2025-08-28-14:45
 */
public class huuEventLoop implements EventLoop{
    //维护一个全局变量作为线程名称
    private static final AtomicInteger THREAD_NAME_COUNTER= new AtomicInteger();

    //阻塞队列
    private final BlockingQueue<Runnable> taskQueue;

    //定时任务队列---PriorityBlockingQueue需要优先级的阻塞队列
    private final PriorityBlockingQueue<ScheduleTask> scheduleTaskQueue;

    //执行任务的线程
    private final Thread thread;

    //唤醒runnable,专门用于唤醒taskqueue,比如获取一个3秒后执行任务，阻塞，但现在来了一个一秒的，需要唤醒执行
    //注意这个唤醒逻辑，这是一个空的runnable
    private static final Runnable WAKE_UP = () -> {};

    public huuEventLoop(){
        taskQueue = new ArrayBlockingQueue<>(1024);
        scheduleTaskQueue = new PriorityBlockingQueue<>(1024);
        thread = new EventLoopThread("huu-eventLoop-thread-" + THREAD_NAME_COUNTER.incrementAndGet());
        thread.start();
    }

    @Override
    public void execute(Runnable runnable) {
        if(!taskQueue.offer(runnable)){
            throw new RuntimeException("task queue is full");
        }
    }

    @Override
    public void schedule(Runnable task, long delay, TimeUnit unit) {
        ScheduleTask scheduleTask = new ScheduleTask(task, this, deadlineMs( delay, unit), -1);
        //这个判定里面就执行了添加
        if (!scheduleTaskQueue.offer(scheduleTask)) {
            throw new RuntimeException("schedule task queue is full");
        }
        execute(WAKE_UP);
    }

    @Override
    public void scheduleAtFixedRate(Runnable task, long initialDelay, long period, TimeUnit unit) {
        ScheduleTask scheduleTask = new ScheduleTask(task, this, deadlineMs( initialDelay, unit), unit.toMillis(period));
        //这个判定里面就执行了添加
        if (!scheduleTaskQueue.offer(scheduleTask)) {
            throw new RuntimeException("schedule task queue is full");
        }
        execute(WAKE_UP);
    }

    private long deadlineMs(long delay, TimeUnit unit){
        return System.currentTimeMillis() + unit.toMillis(delay);
    }

    @Override
    public EventLoop next() {
        return this;
    }

    @Override
    public Queue<ScheduleTask> getScheduleTaskQueue() {
        return scheduleTaskQueue;
    }

    //获取一个阻塞任务中的任务
    private Runnable getTask() {
        ScheduleTask task = scheduleTaskQueue.peek();
        if(task == null){
            Runnable t = null;
            try {
                t = taskQueue.take();
                //返回Null就进入下一次循环也就启到了唤醒的效果
                if(t == WAKE_UP){
                    t = null;
                }
            } catch (InterruptedException ignore) {
                //e.printStackTrace();
            }
            return t;
        }
        //有定时任务
        if (task.getDeadline()<= System.currentTimeMillis()) {
            //peek 方法不会删除,poll真正拿出来
            return scheduleTaskQueue.poll();
        }
        Runnable runnable = null;
        try {
            runnable = taskQueue.poll(task.getDeadline()- System.currentTimeMillis(), TimeUnit.MILLISECONDS);
            if(runnable == WAKE_UP){
                runnable = null;
            }
        } catch (InterruptedException ignore) {
        }
        return runnable;
    }



    private class EventLoopThread extends Thread {

        //重写run方法不断重阻塞队列中拿任务执行
        public EventLoopThread(String name) {
            super(name);
        }
        @Override
        public void run() {
            //死循环,可以尝试维护一个标记位来中断
            while(true){
                Runnable task = getTask();
                if(task != null) {
                    task.run();
                }

            }
        }
    }
}
